/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package certificate.view;

import certificate.controller.MarkController;
import certificate.entity.Course;
import certificate.entity.Student;
import certificate.entity.StudentSubjectStudy;
import certificate.model.MarkModel;
import java.awt.Color;
import java.awt.Component;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.sql.SQLException;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import javax.swing.border.MatteBorder;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableRowSorter;
import javax.swing.text.DefaultFormatterFactory;
import javax.swing.text.NumberFormatter;

/**
 *
 * @author khanh
 */
public class MarkPanel extends javax.swing.JPanel {
    MarkModel model = new MarkModel();
    MarkController controller = new MarkController();
    
    
    /**
     * Creates new form MarkPanel
     */
    public MarkPanel() {
        initComponents();
        tblMark.setDefaultEditor(Integer.class, new IntegerEditor(-1, 10));
        tblMark.setDefaultRenderer(Object.class, new ColourCellRenderer());
        
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        btnSubmit = new javax.swing.JButton();
        lblNameCourse = new javax.swing.JLabel();
        lblIdStudent = new javax.swing.JLabel();
        pnlMarkTable = new javax.swing.JPanel();
        scpMark = new javax.swing.JScrollPane();
        tblMark = new javax.swing.JTable();
        txtIdStudent = new javax.swing.JTextField();
        btnReset = new javax.swing.JButton();
        txtNameStudent = new javax.swing.JTextField();
        lblNameStudent = new javax.swing.JLabel();
        cbbNameCourse = new javax.swing.JComboBox();
        lblIdSubject = new javax.swing.JLabel();
        txtIdSubject = new javax.swing.JTextField();
        lblTitle = new javax.swing.JLabel();

        setPreferredSize(new java.awt.Dimension(787, 477));
        addComponentListener(new java.awt.event.ComponentAdapter() {
            public void componentShown(java.awt.event.ComponentEvent evt) {
                formComponentShown(evt);
            }
        });

        btnSubmit.setText("Submit");
        btnSubmit.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnSubmitActionPerformed(evt);
            }
        });

        lblNameCourse.setText("Course Name : ");

        lblIdStudent.setText("Student ID :");

        tblMark.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {
                "Subject ID", "Subject Name", "Mark"
            }
        ) {
            Class[] types = new Class [] {
                java.lang.String.class, java.lang.String.class, java.lang.String.class
            };

            public Class getColumnClass(int columnIndex) {
                return types [columnIndex];
            }
        });
        scpMark.setViewportView(tblMark);

        javax.swing.GroupLayout pnlMarkTableLayout = new javax.swing.GroupLayout(pnlMarkTable);
        pnlMarkTable.setLayout(pnlMarkTableLayout);
        pnlMarkTableLayout.setHorizontalGroup(
            pnlMarkTableLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlMarkTableLayout.createSequentialGroup()
                .addComponent(scpMark, javax.swing.GroupLayout.PREFERRED_SIZE, 656, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(0, 0, Short.MAX_VALUE))
        );
        pnlMarkTableLayout.setVerticalGroup(
            pnlMarkTableLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlMarkTableLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(scpMark, javax.swing.GroupLayout.DEFAULT_SIZE, 161, Short.MAX_VALUE))
        );

        txtIdStudent.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                txtIdStudentActionPerformed(evt);
            }
        });
        txtIdStudent.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                txtIdStudentFocusLost(evt);
            }
        });

        btnReset.setText("Reset");
        btnReset.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnResetActionPerformed(evt);
            }
        });

        txtNameStudent.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                txtNameStudentActionPerformed(evt);
            }
        });

        lblNameStudent.setText("Student Name : ");

        cbbNameCourse.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cbbNameCourseActionPerformed(evt);
            }
        });

        lblIdSubject.setText("Subject ID or Subject Name :");

        txtIdSubject.addCaretListener(new javax.swing.event.CaretListener() {
            public void caretUpdate(javax.swing.event.CaretEvent evt) {
                txtIdSubjectCaretUpdate(evt);
            }
        });

        lblTitle.setFont(new java.awt.Font("Tahoma", 1, 18)); // NOI18N
        lblTitle.setText("Input Mark Form");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(286, 286, 286)
                .addComponent(lblTitle, javax.swing.GroupLayout.PREFERRED_SIZE, 177, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGap(59, 59, 59)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(pnlMarkTable, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addGroup(layout.createSequentialGroup()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addGroup(layout.createSequentialGroup()
                                        .addComponent(lblIdSubject)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                        .addComponent(txtIdSubject, javax.swing.GroupLayout.PREFERRED_SIZE, 157, javax.swing.GroupLayout.PREFERRED_SIZE))
                                    .addGroup(layout.createSequentialGroup()
                                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                                            .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                                                .addComponent(lblNameCourse)
                                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                                .addComponent(cbbNameCourse, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                                            .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                                                .addComponent(lblIdStudent)
                                                .addGap(27, 27, 27)
                                                .addComponent(txtIdStudent, javax.swing.GroupLayout.PREFERRED_SIZE, 135, javax.swing.GroupLayout.PREFERRED_SIZE)))
                                        .addGap(43, 43, 43)
                                        .addComponent(lblNameStudent)))
                                .addGap(18, 18, 18)
                                .addComponent(txtNameStudent, javax.swing.GroupLayout.PREFERRED_SIZE, 165, javax.swing.GroupLayout.PREFERRED_SIZE))))
                    .addGroup(layout.createSequentialGroup()
                        .addGap(110, 110, 110)
                        .addComponent(btnSubmit)
                        .addGap(27, 27, 27)
                        .addComponent(btnReset)))
                .addGap(0, 72, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(lblTitle, javax.swing.GroupLayout.PREFERRED_SIZE, 29, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(txtIdStudent, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(lblIdStudent)
                    .addComponent(lblNameStudent)
                    .addComponent(txtNameStudent, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(lblNameCourse)
                    .addComponent(cbbNameCourse, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(17, 17, 17)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(lblIdSubject)
                    .addComponent(txtIdSubject, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(pnlMarkTable, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(34, 34, 34)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(btnReset)
                    .addComponent(btnSubmit))
                .addContainerGap(87, Short.MAX_VALUE))
        );
    }// </editor-fold>//GEN-END:initComponents

    private void txtIdStudentActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtIdStudentActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_txtIdStudentActionPerformed

    private void txtNameStudentActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtNameStudentActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_txtNameStudentActionPerformed

    private void cbbNameCourseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbbNameCourseActionPerformed
        try {
            String idStudent = model.getStudentId();
            String idCourse = model.getCbbModel().getSelectedCourse().getIdCourse();
            
            List<StudentSubjectStudy> list = controller.getAllStudentSubjectStudy(idStudent, idCourse);

            // update Model
            if(list != null){
                model.setTblMark(list);
            }
            
            // Display model
            tblMark.setModel(model.getTblMark());
            
        } catch (SQLException ex) {
            Logger.getLogger(MarkPanel.class.getName()).log(Level.SEVERE, null, ex);
        }
        
    }//GEN-LAST:event_cbbNameCourseActionPerformed

    private void txtIdStudentFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtIdStudentFocusLost
        model.setStudentId(txtIdStudent.getText());
        Student s = null;
        List<Course> list = null;
        try {
            s = controller.getStudentById(model.getStudentId());
            list = controller.getCourseOfStudent(model.getStudentId());
        } catch (SQLException ex) {
            Logger.getLogger(MarkPanel.class.getName()).log(Level.SEVERE, null, ex);
        }
        if(s != null && list != null){
            model.setStudentName(s.getName());
            model.setCbbModel(list);
            
            
            txtNameStudent.setText(s.getName());
            cbbNameCourse.setModel(model.getCbbModel());
            txtIdStudent.setBackground(Color.white);
            
            cbbNameCourse.setSelectedIndex(0);
        }else {
            txtIdStudent.setBackground(Color.red);
        }
    }//GEN-LAST:event_txtIdStudentFocusLost

    private void formComponentShown(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_formComponentShown
        txtIdStudent.requestFocusInWindow();
    }//GEN-LAST:event_formComponentShown

    private void txtIdSubjectCaretUpdate(javax.swing.event.CaretEvent evt) {//GEN-FIRST:event_txtIdSubjectCaretUpdate
        String text = txtIdSubject.getText();
        TableRowSorter<MarkModel.SubjectStudentModel> sortter = new TableRowSorter<MarkModel.SubjectStudentModel>(model.getTblMark());
        sortter.setRowFilter(RowFilter.regexFilter(text));
        tblMark.setRowSorter(sortter);
    }//GEN-LAST:event_txtIdSubjectCaretUpdate

    private void btnResetActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnResetActionPerformed
        txtIdStudentFocusLost(null);
    }//GEN-LAST:event_btnResetActionPerformed

    private void btnSubmitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSubmitActionPerformed
        
        // Update model to Database
        // true if success, false if error (when that, transaction rollback)
        if(!controller.updateModel(model)){
            JOptionPane.showMessageDialog(this, "Update Mark Error!, Try again");
        }else {
            JOptionPane.showMessageDialog(this, "Update Mark success");
            btnResetActionPerformed(null);
        }
        
    }//GEN-LAST:event_btnSubmitActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnReset;
    private javax.swing.JButton btnSubmit;
    private javax.swing.JComboBox cbbNameCourse;
    private javax.swing.JLabel lblIdStudent;
    private javax.swing.JLabel lblIdSubject;
    private javax.swing.JLabel lblNameCourse;
    private javax.swing.JLabel lblNameStudent;
    private javax.swing.JLabel lblTitle;
    private javax.swing.JPanel pnlMarkTable;
    private javax.swing.JScrollPane scpMark;
    private javax.swing.JTable tblMark;
    private javax.swing.JTextField txtIdStudent;
    private javax.swing.JTextField txtIdSubject;
    private javax.swing.JTextField txtNameStudent;
    // End of variables declaration//GEN-END:variables

}

/**
 * Implements a cell editor that uses a formatted text field
 * to edit Integer values.
 */
class IntegerEditor extends DefaultCellEditor {
    JFormattedTextField ftf;
    NumberFormat integerFormat;
    private Integer minimum, maximum;
    private boolean DEBUG = false;
 
    public IntegerEditor(int min, int max) {
        super(new JFormattedTextField());
        ftf = (JFormattedTextField)getComponent();
        minimum = new Integer(min);
        maximum = new Integer(max);
 
        //Set up the editor for the integer cells.
        integerFormat = NumberFormat.getIntegerInstance();
        NumberFormatter intFormatter = new NumberFormatter(integerFormat);
        intFormatter.setFormat(integerFormat);
        intFormatter.setMinimum(minimum);
        intFormatter.setMaximum(maximum);
 
        ftf.setFormatterFactory(
                new DefaultFormatterFactory(intFormatter));
        ftf.setValue(minimum);
        ftf.setHorizontalAlignment(JTextField.CENTER);
        ftf.setFocusLostBehavior(JFormattedTextField.PERSIST);
 
        setClickCountToStart(1);
        
        //React when the user presses Enter while the editor is
        //active.  (Tab is handled as specified by
        //JFormattedTextField's focusLostBehavior property.)
        ftf.getInputMap().put(KeyStroke.getKeyStroke(
                                        KeyEvent.VK_ENTER, 0),
                                        "check");
        ftf.getActionMap().put("check", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
        if (!ftf.isEditValid()) { //The text is invalid.
                    if (userSaysRevert()) { //reverted
                ftf.postActionEvent(); //inform the editor
            }
                } else try {              //The text is valid,
                    ftf.commitEdit();     //so use it.
                    ftf.postActionEvent(); //stop editing
                } catch (java.text.ParseException exc) { }
            }
        });
    }
 
    //Override to invoke setValue on the formatted text field.
    @Override
    public Component getTableCellEditorComponent(JTable table,
            Object value, boolean isSelected,
            int row, int column) {
        JFormattedTextField jftf =
            (JFormattedTextField)super.getTableCellEditorComponent(
                table, value, isSelected, row, column);
        jftf.setValue(value);
        return jftf;
    }
 
    //Override to ensure that the value remains an Integer.
    @Override
    public Object getCellEditorValue() {
        JFormattedTextField jftf = (JFormattedTextField)getComponent();
        Object o = jftf.getValue();
        if (o instanceof Integer) {
            return o;
        } else if (o instanceof Number) {
            return new Integer(((Number)o).intValue());
        } else {
            if (DEBUG) {
                System.out.println("getCellEditorValue: o isn't a Number");
            }
            try {
                return integerFormat.parseObject(o.toString());
            } catch (ParseException exc) {
                System.err.println("getCellEditorValue: can't parse o: " + o);
                return null;
            }
        }
    }
 
    //Override to check whether the edit is valid,
    //setting the value if it is and complaining if
    //it isn't.  If it's OK for the editor to go
    //away, we need to invoke the superclass's version
    //of this method so that everything gets cleaned up.
    @Override
    public boolean stopCellEditing() {
        JFormattedTextField jftf = (JFormattedTextField)getComponent();
        if (jftf.isEditValid()) {
            try {
                jftf.commitEdit();
                // Thay doi mau sac cua hang tuong ung
                
            } catch (java.text.ParseException exc) { }
         
        } else { //text is invalid
            if (!userSaysRevert()) { //user wants to edit
            return false; //don't let the editor go away
        }
        }
        return super.stopCellEditing();
    }
 
    /**
     * Lets the user know that the text they entered is
     * bad. Returns true if the user elects to revert to
     * the last good value.  Otherwise, returns false,
     * indicating that the user wants to continue editing.
     */
    protected boolean userSaysRevert() {
        Toolkit.getDefaultToolkit().beep();
        ftf.selectAll();
        Object[] options = {"Edit",
                            "Revert"};
        int answer = JOptionPane.showOptionDialog(
            SwingUtilities.getWindowAncestor(ftf),
            "The value must be an integer between "
            + minimum + " and "
            + maximum + ".\n"
            + "You can either continue editing "
            + "or revert to the last valid value.",
            "Invalid Text Entered",
            JOptionPane.YES_NO_OPTION,
            JOptionPane.ERROR_MESSAGE,
            null,
            options,
            options[1]);
         
        if (answer == 1) { //Revert!
            ftf.setValue(ftf.getValue());
        return true;
        }
    return false;
    }
    
    
    
}

class ColourCellRenderer extends DefaultTableCellRenderer{

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        MarkModel.SubjectStudentModel model = (MarkModel.SubjectStudentModel)table.getModel();
        Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        JComponent jc = (JComponent)c;
        Color rowColour = model.getRowColour(row);
        jc.setBackground(rowColour);
        return c;
    }
        
}